module dwt.util.eventhandler;

private import dwt.dwt;

private import dwt.events.events;
private import dwt.events.typedevent;
private import dwt.util.util;
private import dwt.widgets.event;

version(OLE_COM){
	private import dwt.ole.win32.olemisc;
}

// required for template-class to generate library  
int foo;


public interface TypedHandler
{
	int eventType();
	boolean equals(TypedHandler h);
	// Object[] cDatas();
	Object cData();
	void handleEvent(Event e);
	version(OLE_COM){
		void handleEvent(OleEvent e);
	}
}

// E can be Event or OleEvent
class EventHandlerT(E) : TypedHandler 
{
	private void delegate(E)	_handler;
	private void delegate() 	_handler2;

	// The custom data Object
	// private Object[] _cDatas;
	private Object _cData;
	
	private int _eventType;
	
	// Note : "customData" can be null;
	public this(Object customData, int type, void delegate(E) handler) { 
		assert(handler);
		_eventType = type;
		_handler = handler;
		_cData = customData;
	}

	// deprecated: for simple and robust purpose, none parameters delegate is not support any more, use the one with Event parameter
	public deprecated this(Object customData, int type, void delegate() handler){
		assert(handler);
		_eventType = type;
		_handler2 = handler;
		_cData = customData;
	}
	
	// Array accepted
/* 	public this(Object[] customDatas, int type, void delegate(E) handler) { 
		assert(handler);
		_eventType = type;
		_handler = handler;
		_cDatas = customDatas;
	} */

	// deprecated: for simple and robust purpose, none parameters delegate is not support any more, use the one with Event parameter
/* 	public deprecated this(Object[] customDatas, int type, void delegate() handler){
		assert(handler);
		_eventType = type;
		_handler2 = handler;
		_cDatas = customDatas;
	} */
	public int eventType() { return _eventType;}
	public void delegate(E) handler() { return _handler;}
	// public Object[] cDatas() {return _cDatas;}
	public Object cData() { return _cData; }
	public void delegate() handler2() { return _handler2;};
	
	public boolean equals(TypedHandler h) {
		EventHandlerT hand = cast(EventHandlerT) h;
		if(hand && hand.eventType == _eventType) {
			if(this._handler && this._handler is hand.handler() )
				return true;
			else if(this._handler2 && this._handler2 is hand.handler2())
				return true;		
		}
		return false; 
	}
	
	/**
	 * <Shawn> This method is the implementation of interface TypedHandler,
	 * actually, it should never be called.
	 */
	version(OLE_COM){ 
		public void handleEvent (OleEvent e) {
			// none parameter delegate
			if(_handler2){
				_handler2();
				return;
			}

			// e.cDatas = _cDatas;
			e.cData = _cData;
			_handler(cast(E)e);
		}
	}
	
	/**
	 * Handles the given event.
	 * <p>
	 * <b>IMPORTANT:</b> This method is <em>not</em> part of the DWT
	 * public API. It is marked public only so that it can be shared
	 * within the packages provided by DWT. It should never be
	 * referenced from application code.
	 * </p>
	 */
	public void handleEvent (Event e) {
		if(e is null) return;
		
		debug{
			if(e.type != _eventType){
				Util.trace(__FILE__, ", Event Type not match !!!");
				assert(0);
			}
		}
		
		// none parameter delegate
		if(_handler2){
			_handler2();
			return;
		}

		// e.cDatas = _cDatas;
		e.cData = _cData;
		_handler(cast(E)e);
	}
}	// end of EventHandler

alias EventHandlerT!(Event) 	EventHandler;

version(OLE_COM){
alias EventHandlerT!(OleEvent)	OleEventHandler;
}

// <Shawn>
// Note : don't implement E as (Event) or (OleEvent)
// Event/OleEvent shoud be implemented using EventHandlerT() in the above
class HandlerT(E) : TypedHandler {

	private alias void delegate(E) T;
	private T _handler;
	private void delegate() _handler2;

	// The custom data Object
	// private Object[] _cDatas;
	private Object _cData;
	
	private int _eventType;
	
	// Note : "customData" can be null;
	public this(Object customData, int type, T handler) { 
		assert(handler);
		_eventType = type;
		_handler = handler;
		_cData = customData;
	}

	// deprecated: for simple and robust purpose, none parameters delegate is not support any more, use the one with Event parameter
	public deprecated this(Object customData, int type, void delegate() handler){
		assert(handler);
		_eventType = type;
		_handler2 = handler;
		_cData = customData;
	}

	// Array accepted	
	public this(Object[] customDatas, int type, T handler) { 
		assert(handler);
		_eventType = type;
		_handler = handler;
		// _cDatas = customDatas;
	}

	// deprecated: for simple and robust purpose, none parameters delegate is not support any more, use the one with Event parameter
	public deprecated this(Object[] customDatas, int type, void delegate() handler){
		assert(handler);
		_eventType = type;
		_handler2 = handler;
		// _cDatas = customDatas;
	}	

	public int eventType() { return _eventType;}
	public T handler() { return _handler;}
	// public Object[] cDatas() {return _cDatas;}
	public Object cData() {return _cData;}
	public void delegate() handler2() { return _handler2;};
	
	public boolean equals(TypedHandler h) {
		HandlerT hand = cast(HandlerT) h;
		if(hand && hand.eventType == _eventType) {
			if(this._handler && this._handler is hand.handler() )
				return true;
			else if(this._handler2 && this._handler2 is hand.handler2())
				return true;		
		}
		return false; 
	}
	
	/**
	 * <Shawn> This method is the implementation of interface TypedHandler,
	 * actually, it should never be called.
	 */
	version(OLE_COM){ 
		public void handleEvent (OleEvent e) {
			if(e is null) return;
			
			assert(0);
		}
	}
	
	/**
	 * Handles the given event.
	 * <p>
	 * <b>IMPORTANT:</b> This method is <em>not</em> part of the DWT
	 * public API. It is marked public only so that it can be shared
	 * within the packages provided by DWT. It should never be
	 * referenced from application code.
	 * </p>
	 */
	public void handleEvent (Event e) {
		if(e is null) return;
		
		debug{
			if(e.type != _eventType){
				Util.trace(__FILE__, ", Event Type not match !!!");
				assert(0);
			}
		}
		
		// none parameter delegate
		if(_handler2){
			_handler2();
			return;
		}

		e.cData = _cData;
		// e.cDatas = _cDatas;
		E evt = new E(e);
		_handler(evt);
		
		switch (_eventType) {
			case DWT.Paint: {
				/* Field set by Control */
				PaintEvent event = cast(PaintEvent)evt;
				e.gc = event.gc;
				break;
			}			
			case DWT.Selection: {
				/* Fields set by Sash */
				SelectionEvent event = cast(SelectionEvent)evt;
				e.x = event.x;
				e.y = event.y;
				e.doit = event.doit;
				break;
			}
			case DWT.DefaultSelection: {
				break;
			}
			case DWT.Dispose: {
				break;
			}
			case DWT.FocusIn: {
				break;
			}
			case DWT.FocusOut: {
				break;
			}
			case DWT.Hide: {
				break;
			}
			case DWT.Show: {
				break;
			}
			case DWT.KeyDown: {
				KeyEvent event = cast(KeyEvent)(evt);
				e.doit = event.doit;
				break;
			}
			case DWT.KeyUp: {
				KeyEvent event = cast(KeyEvent)(evt);
				e.doit = event.doit;
				break;
			}
			case DWT.MouseDown: {
				break;
			}
			case DWT.MouseUp: {
				break;
			}			
			case DWT.MouseDoubleClick: {
				break;
			}
			case DWT.MouseMove: {
				return;
			}
			case DWT.Resize: {
				break;
			}
			case DWT.Move: {
				break;
			}
			case DWT.Close: {
				// Fields set by Decorations 
				ShellEvent event = cast(ShellEvent)evt;
				e.doit = event.doit;
				break;
			}
			case DWT.Activate: {
				break;
			}
			case DWT.Deactivate: {
				break;
			}
			case DWT.Iconify: {
				break;
			}
			case DWT.Deiconify: {
				break;
			}
			case DWT.Expand: {
				break;
			}
			case DWT.Collapse: {
				break;
			}
			case DWT.Modify: {
				break;
			}
			case DWT.Verify: {
				// Fields set by Text, RichText 
				VerifyEvent event =cast(VerifyEvent)evt;
				e.text = event.text;
				e.doit = event.doit;
				break;
			}
			case DWT.Help: {
				break;
			}
			case DWT.Arm: {
				break;
			}
			case DWT.MouseExit: {
				break;
			}
			case DWT.MouseEnter: {
				break;
			}
			case DWT.MouseHover: {
				break;
			}
			case DWT.Traverse: {
				// Fields set by Control
				TraverseEvent event = cast(TraverseEvent)evt;
				e.detail = event.detail;
				e.doit = event.doit;
				break;
			}		
			default : break;
		}
	}
}	// end of HandlerT!()


alias HandlerT!(ArmEvent) 			ArmHandler;
alias HandlerT!(ControlEvent) 		ControlHandler;
alias HandlerT!(DisposeEvent) 		DisposeHandler;
alias HandlerT!(FocusEvent) 		FocusHandler;
alias HandlerT!(HelpEvent) 			HelpHandler;
alias HandlerT!(KeyEvent) 			KeyHandler;
alias HandlerT!(MenuEvent) 			MenuHandler;
alias HandlerT!(ModifyEvent) 		ModifyHandler;
alias HandlerT!(MouseEvent) 		MouseHandler;
alias HandlerT!(PaintEvent) 		PaintHandler;
alias HandlerT!(SelectionEvent) 	SelectionHandler;
alias HandlerT!(ShellEvent) 		ShellHandler;
alias HandlerT!(TraverseEvent)		TraverseHandler;
alias HandlerT!(TreeEvent) 			TreeHandler;
alias HandlerT!(VerifyEvent)		VerifyHandler;


alias void delegate()					GeneralDelegate;
alias void delegate(ArmEvent) 			ArmDelegate;
alias void delegate(ControlEvent) 		ControlDelegate;
alias void delegate(DisposeEvent) 		DisposeDelegate;
alias void delegate(Event)				EventDelegate;
alias void delegate(FocusEvent) 		FocusDelegate;
alias void delegate(HelpEvent) 			HelpDelegate;
alias void delegate(KeyEvent) 			KeyDelegate;
alias void delegate(MenuEvent) 			MenuDelegate;
alias void delegate(ModifyEvent) 		ModifyDelegate;
alias void delegate(MouseEvent) 		MouseDelegate;
alias void delegate(PaintEvent) 		PaintDelegate;
alias void delegate(SelectionEvent) 	SelectionDelegate;
alias void delegate(ShellEvent) 		ShellDelegate;
alias void delegate(TraverseEvent)		TraverseDelegate;
alias void delegate(TreeEvent) 			TreeDelegate;
alias void delegate(VerifyEvent)		VerifyDelegate;







